package 中等.搜索.广度优先搜索;

/**
 * 有 n 个城市，其中一些彼此相连，另一些没有相连。如果城市 a 与
 * 城市 b 直接相连，且城市 b 与城市 c 直接相连，那么城市 a 与
 * 城市 c 间接相连。
 * 省份 是一组直接或间接相连的城市，组内不含其他没有相连的城市。
 * 给你一个 n x n 的矩阵 isConnected ，其中 isConnected[i][j] = 1
 * 表示第 i 个城市和第 j 个城市直接相连，而 isConnected[i][j] = 0
 * 表示二者不直接相连。
 * 返回矩阵中 省份 的数量。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/number-of-provinces
 */
public class 省份数量_547 {

    public static void main(String[] args) {

    }

    /**
     * 并查集
     * 将城市连通起来，看最后有多少个根节点，即为城市的数量
     */
    public int findCircleNum(int[][] isConnected) {
        int cnt = 0;
        DSU dsu = new DSU(isConnected.length);

        for (int i = 0; i < isConnected.length; i++) {
            for (int j = 0; j < isConnected[0].length; j++) {
                if (isConnected[i][j] == 1) {
                    dsu.union(i, j);
                }
            }
        }

        for (int i = 0; i < dsu.pre.length; i++) {
            if (dsu.pre[i] == i) {
                cnt++;
            }
        }
        return cnt;
    }

    static class DSU {
        private int[] pre;

        public DSU(int n) {
            pre = new int[n];
            for (int i = 0; i < pre.length; i++) {
                pre[i] = i;
            }
        }

        public int find(int x) {
            if (pre[x] == x) {
                return x;
            }
            return pre[x] = find(pre[x]);
        }

        public void union(int x, int y) {
            x = find(x);
            y = find(y);
            if (x == y) return;
            pre[x] = y;
        }
    }

}
